package com.huaxin.dss2.util;

import java.util.*;

/**
 * Created by qq102 on 2017/6/7.
 */
public class MathUtil {


    private static boolean isRightFormat = true;

    public static String symbol = "+-*/()";

    public static double getResult(String formula){
        double returnValue = 0;
        try{
            returnValue = doAnalysis(formula);
        }catch(NumberFormatException nfe){
            System.out.println("公式格式有误，请检查:" + formula);
        }catch(Exception e){
            e.printStackTrace();
        }
        if(!isRightFormat){
            System.out.println("公式格式有误，请检查:" + formula);
        }
        return returnValue;
    }

    private static double doAnalysis(String formula){
        double returnValue = 0;
        LinkedList<Integer> stack = new LinkedList<Integer>();
        int curPos = 0;
        String beforePart = "";
        String afterPart = "";
        String calculator = "";
        isRightFormat = true;
        try {
            while(isRightFormat&&(formula.indexOf('(') >= 0||formula.indexOf(')') >= 0)){
                curPos = 0;
                for(char s : formula.toCharArray()){
                    if(s == '('){
                        stack.add(curPos);
                    }else if(s == ')'){
                        if(stack.size() > 0){
                            beforePart = formula.substring(0, stack.getLast());
                            afterPart = formula.substring(curPos + 1);
                            calculator = formula.substring(stack.getLast() + 1, curPos);
                            formula = beforePart + doCalculation(calculator) + afterPart;
                            stack.clear();
                            break;
                        }else{
                            System.out.println("有未关闭的右括号！");
                            isRightFormat = false;
                        }
                    }
                    curPos++;
                }
                if(stack.size() > 0){
                    System.out.println("有未关闭的左括号！");
                    break;
                }
            }
        }catch (Exception e){
            System.out.println("公式错误：" + formula);
        }


        if(isRightFormat){
            returnValue = doCalculation(formula);
        }
        return returnValue;
    }

    private static double doCalculation(String formula) {
        ArrayList<Double> values = new ArrayList<Double>();
        ArrayList<String> operators = new ArrayList<String>();
        int curPos = 0;
        int prePos = 0;
        int minus = 0;
        for (char s : formula.toCharArray()) {
            if ((s == '+' || s == '-' || s == '*' || s == '/') && minus !=0 && minus !=2) {
                values.add(Double.parseDouble(formula.substring(prePos, curPos).trim()));
                operators.add("" + s);
                prePos = curPos + 1;
                minus = minus +1;
            }else{
                minus =1;
            }
            curPos++;
        }
        values.add(Double.parseDouble(formula.substring(prePos).trim()));
        char op;
        for (curPos = 0; curPos <= operators.size() - 1; curPos++) {
            op = operators.get(curPos).charAt(0);
            switch (op) {
                case '*':
                    values.add(curPos, values.get(curPos) * values.get(curPos + 1));
                    values.remove(curPos + 1);
                    values.remove(curPos + 1);
                    operators.remove(curPos);
                    curPos = -1;
                    break;
                case '/':
                    values.add(curPos, values.get(curPos) / values.get(curPos + 1));
                    values.remove(curPos + 1);
                    values.remove(curPos + 1);
                    operators.remove(curPos);
                    curPos = -1;
                    break;
            }
        }
        for (curPos = 0; curPos <= operators.size() - 1; curPos++) {
            op = operators.get(curPos).charAt(0);
            switch (op) {
                case '+':
                    values.add(curPos, values.get(curPos) + values.get(curPos + 1));
                    values.remove(curPos + 1);
                    values.remove(curPos + 1);
                    operators.remove(curPos);
                    curPos = -1;
                    break;
                case '-':
                    values.add(curPos, values.get(curPos) - values.get(curPos + 1));
                    values.remove(curPos + 1);
                    values.remove(curPos + 1);
                    operators.remove(curPos);
                    curPos = -1;
                    break;
            }
        }
        return values.get(0).doubleValue();
    }

    public static Double getFormulaValue(String formula,Map<String,Double> dataMap){
//        System.out.println(MathUtil.getResult("0+0*2"));
//        System.out.println(MathUtil.getResult("7/2-(-4)"));
//        System.out.println(MathUtil.getResult("1287763200000-1276272000000")/(3600*24*1000));
        formula = replaceStr(formula,dataMap);
    //    System.out.println("formula:" + formula);
        if (formula==null){
            return null;
        }
        return MathUtil.getResult(formula);
  //      replaceStr("(CPB4K9_110_j3)+(CPB4K9_110_ky)*2");
    }

    public static String replaceStr(String formula,Map<String,Double> dataMap){
     //   System.out.println(formula);
        String newFormula = "";
        boolean tag = true;
        for (int i=0;i<formula.length();i++){
           if (symbol.contains(formula.substring(i,i+1))){
               newFormula+=",";
           }else {
               newFormula+=formula.substring(i,i+1);
           }
        }
        for (String a:newFormula.split(",")){
            if (a!=""&&a.split("_").length==3){
                if (dataMap.get(a)!=null){
                   formula = formula .replaceAll(a,dataMap.get(a).toString());
                }else {
                    return null;
                }
            }
        }

        return formula;
    }

//    public static void  main(String args[]){
//        replaceStr("adasdas_01_01",null);
//    }

}
